package com.yungu.swift.assets.driver.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.yungu.swift.assets.config.ApplicationConfig;
import com.yungu.swift.assets.driver.model.dto.DriverHeatMapDto;
import com.yungu.swift.assets.driver.model.param.HeatMapConfigParam;
import com.yungu.swift.assets.driver.model.param.HeatMapInfoParam;
import com.yungu.swift.assets.driver.model.vo.HeatMapConfigVo;
import com.yungu.swift.assets.driver.model.vo.HeatMapInfoVo;
import com.yungu.swift.assets.driver.service.DriverHeatMapService;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.model.config.DriverConfig;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.lbs.model.Coordinate;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author : cuixiuyin
 * @date : 2019/4/22
 */
@Slf4j
@Service
public class DriverHeatMapServiceImpl implements DriverHeatMapService {

    @Autowired
    private RedisCacheService redisCacheService;
    @Reference
    private OrderDetailService orderDetailService;

    private static final String HEAT_MAP_PREFIX = "HEAT_MAP";
    /**
     * 全业务
     */
    private static final Integer CONFIG_BUSINESS_ALL = 0;

    private Lock lock = new ReentrantLock();


    @Override
    public ResponseData<HeatMapConfigVo> getHeatMapConfig(HeatMapConfigParam configParam) {
        DriverConfig.HomeBean home = ApplicationConfig.DRIVER_CONFIG.getHome();
        // 构建返回信息
        HeatMapConfigVo heatMapConfigVO = new HeatMapConfigVo();
        if (home != null) {
            DriverConfig.HomeBean.HeatMapBean heatMap = home.getHeatMap();
            if (heatMap != null) {
                switch (configParam.getBusinessType()) {
                    case CommonConstant.BUSINESS_TYPE_TAXI:
                        DriverConfig.HomeBean.HeatMapBean.HeatMap heatMapTaxi = heatMap.getTaxi();
                        heatMapConfigVO.setRange(heatMapTaxi.getRange());
                        heatMapConfigVO.setInterval(heatMapTaxi.getInterval());
                        break;
                    case CommonConstant.BUSINESS_TYPE_SPEC:
                        DriverConfig.HomeBean.HeatMapBean.HeatMap heatMapSpecial = heatMap.getSpecial();
                        heatMapConfigVO.setRange(heatMapSpecial.getRange());
                        heatMapConfigVO.setInterval(heatMapSpecial.getInterval());
                        break;
                    case CommonConstant.BUSINESS_TYPE_EXPRESS:
                        DriverConfig.HomeBean.HeatMapBean.HeatMap heatMapExpress = heatMap.getExpress();
                        heatMapConfigVO.setRange(heatMapExpress.getRange());
                        heatMapConfigVO.setInterval(heatMapExpress.getInterval());
                        break;
                    case CommonConstant.BUSINESS_ALL:
                        DriverConfig.HomeBean.HeatMapBean.HeatMap heatMapAll = heatMap.getAll();
                        heatMapConfigVO.setRange(heatMapAll.getRange());
                        heatMapConfigVO.setInterval(heatMapAll.getInterval());
                        break;
                    default:
                        break;

                }
            }
        }
        return ResponseData.buildSuccessResponse(heatMapConfigVO);
    }

    @Override
    public ResponseData<HeatMapInfoVo> getHeatMapInfo(HeatMapInfoParam infoParam) {
        Object object = redisCacheService.get(HEAT_MAP_PREFIX + StringUtils.left(infoParam.getAdCode(), 4) + "00"
                + infoParam.getBusinessType());
        if (object != null) {
            HeatMapInfoVo heatMapInfoVO = new HeatMapInfoVo();
            heatMapInfoVO.setCoordinates((List<Coordinate>) object);
            return ResponseData.buildSuccessResponse(heatMapInfoVO);
        }
        // 手动缓存一次
        try {
            //避免缓存击穿
            lock.lock();
            cacheHeatMapInfo(infoParam.getAppid());
        } finally {
            lock.unlock();
        }
        return ResponseData.buildSuccessResponse(null);
    }

    @Override
    public ResponseData<Boolean> cacheHeatMapInfo(String appid) {
        // 获得业务的配置信息
        DriverConfig.HomeBean home = ApplicationConfig.DRIVER_CONFIG.getHome();
        if (home != null) {
            DriverConfig.HomeBean.HeatMapBean heatMapBean = home.getHeatMap();
            if (heatMapBean != null && heatMapBean.getAll() != null) {
                heapMapOrderStatis(CommonConstant.BUSINESS_ALL, heatMapBean.getAll().getInterval());
            }
            if (heatMapBean != null && heatMapBean.getExpress() != null) {
                heapMapOrderStatis(CommonConstant.BUSINESS_TYPE_EXPRESS, heatMapBean.getExpress().getInterval());
            }
            if (heatMapBean != null && heatMapBean.getSpecial() != null) {
                heapMapOrderStatis(CommonConstant.BUSINESS_TYPE_SPEC, heatMapBean.getSpecial().getInterval());
            }
            if (heatMapBean != null && heatMapBean.getTaxi() != null) {
                heapMapOrderStatis(CommonConstant.BUSINESS_TYPE_TAXI, heatMapBean.getTaxi().getInterval());
            }
        }
        return ResponseData.buildSuccessResponse("热力图统计成功", Boolean.TRUE);
    }

    private void heapMapOrderStatis(Integer type, Integer interval) {
        List<DriverHeatMapDto> heatMapDtos = orderDetailService.heapMapOrderStatis(type, interval).getData();
        if (CollectionUtils.isNotEmpty(heatMapDtos)) {
            Map<String, List<Coordinate>> collect = heatMapDtos.stream().collect(Collectors.groupingBy(
                    heatMapDto -> StringUtils.left(heatMapDto.getAdCode(), 4) + "00",
                    Collectors.mapping(heatMapDto -> {
                        Coordinate coordinate = new Coordinate();
                        coordinate.setLng(heatMapDto.getStartLng());
                        coordinate.setLat(heatMapDto.getStartLat());
                        return coordinate;
                    }, Collectors.toList())));
            if (collect != null) {
                collect.forEach((adcode, coordinates) -> {
                    String key = HEAT_MAP_PREFIX + adcode + type;
                    redisCacheService.set(key, coordinates, interval.longValue());
                });
            }
            return;
        }
        String pattern = HEAT_MAP_PREFIX + "*" + type;
        Set<String> keys = redisCacheService.keys(pattern);
        if (CollectionUtils.isNotEmpty(keys)) {
            redisCacheService.deleteKeys(keys);
        }
        log.debug("未统计到相关热力图订单数据，businessType：{}", type);
    }
}
